package cn.learn.pay.wechat.util;

import cn.learn.util.IoUtils;
import org.apache.commons.codec.binary.Base64;
import org.springframework.util.Assert;

import java.io.IOException;
import java.io.InputStream;
import java.security.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;

/**
 * 签名工具类
 * https://github.com/wechatpay-apiv3/wechatpay-apache-httpclient/tree/v0.2.2
 *
 * @author huangyezhan
 * @version 1.0
 * @date 2021年08月28日11:40
 */
public class keyPairUtil {

    /**
     * 获取私钥对象
     *
     * @param privateKeyContent 私钥的字符串
     * @return 返回私钥对象
     * @throws IOException 异常
     */
    public static PrivateKey getPrivateKey(String privateKeyContent) throws IOException {
        try {
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decodeBase64(privateKeyContent));
            KeyFactory          kf      = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(keySpec);
        } catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("当前Java环境不支持RSA", e);
        } catch (InvalidKeySpecException e) {
            throw new RuntimeException("无效的密钥格式");
        }
    }

    public static PrivateKey getPrivateKeyByResource(String path) {
        try (InputStream inputStream = keyPairUtil.class.getClassLoader().getResourceAsStream(path)) {
            Assert.notNull(inputStream,"证书内容不能为空！");
            String content = IoUtils.ioAll2String(inputStream);
            return getPrivateKey(deleteSign(content));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 生成RSA公、私钥对
     *
     * @return 结果
     * @throws NoSuchAlgorithmException 异常
     */
    public static KeyPair generatorKeyPair() throws NoSuchAlgorithmException {
        // 实例化密钥生成器
        KeyPairGenerator rsa = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥生成器，要是64的倍数，默认为1024
        rsa.initialize(1024);
        // 生成密钥对
        KeyPair keyPair = rsa.generateKeyPair();
        // 公钥
        PublicKey publicKey = keyPair.getPublic();
        // 私钥
        PrivateKey privateKey = keyPair.getPrivate();
        return keyPair;
    }

    // 去掉证书的头尾
    private static String deleteSign(String privateKeyContent) {
        return privateKeyContent.replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replaceAll("\\s+", "");
    }

}
